package com.sumainfor.pc.market.controller.jianrongjiayuan;






import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.Map;

@Controller
@RequestMapping("/GuomiClientDemo")
public class GuomiClientDemo {

	private static String secureType = "guomiSM";

	public static void useage(){
		System.out.println("Usage: java -jar GuomiClientDemo.jar 服务器地址 服务器端口 服务器域名 服务器URL 节点号 消息文件");
		System.out.println("       服务器地址：远端HTTP服务器的IP地址");
		System.out.println("       服务器端口：远端HTTP服务器的服务端口");
		System.out.println("       服务器域名：远端HTTP服务器的域名，如果对方未指定域名请输入localhost");
		System.out.println("       服务器URL：远端HTTP服务器的URL，必须从/开始");
		System.out.println("       节点号：系统分配的节点号");
		System.out.println("       消息文件：待发送的消息文件路径，输入overall时只输出密钥");
	}

//	public static void main(String[] args) throws Exception {
//		//获取传入参数
//		String serverIP    = "124.127.94.44";
//		String serverPort  = "32800";
//		String serverHost  = "www.ccb.com";
//		String serverUrl   = "/HPCZH";
//		String nodeid      = "ZHQYMF";
////		String messageFile = "P5HPCBDC";
//		String messageFile = "";
//		SendAndRecv(serverIP,serverPort,serverHost,serverUrl,nodeid,messageFile);
//	}


	@PostMapping("/ceshi")
	@ResponseBody
	public String  ceshi(@RequestBody Map<String,Object> params) throws Exception{

		//获取传入参数
		String serverIP    = "124.127.94.44";
		String serverPort  = "32800";
		String serverHost  = "www.ccb.com";
		String serverUrl   = "/HPCZH";
		String nodeid      = "ZHQYMF";
//		String messageFile = "P5HPCBDC";
		String messageFile = "";
		SendAndRecv(serverIP,serverPort,serverHost,serverUrl,nodeid,messageFile);

		return "成功";

	}

	private static boolean SendAndRecv(String serverIP,String serverPort,String serverHost,String serverUrl,String nodeid,String messageFile) throws Exception
	{
		//获取会话密钥，设置加解密参数
		SecureTool secureTool = new SecureTool();
		if(secureTool.updateKeyInfo(secureType,nodeid) == false) return false;
		secureTool.printSessionKey();
		if(messageFile.equalsIgnoreCase("overall")) return true;//如果只是打印密钥，则直接返回

		//交易类型标记 0:正常 1:签到
		String singType = "0";
		System.out.printf("secureType=[%s] serverIP=[%s] serverPort=[%s] nodeId=[%s]\n",secureType,serverIP,serverPort,nodeid);

		//原始报文，直接从文件读取
		byte[] messageBody = null;
		if(singType.equalsIgnoreCase("0")) { //需要加密
			String signMessage = MessageTool.getFilePathMessage();
			byte[] messageByte = signMessage.getBytes();
			System.out.printf("原始报文message=[%d] [%s]\n",messageByte.length,new String(messageByte,"UTF-8"));
			messageBody = secureTool.encrypt(messageByte); //加密
			NetTool.printEncMessage("加密后的报文",messageBody,messageBody.length);
		} else {
			String signMessage = MessageTool.getQiandaoMessage();
			System.out.printf("原始报文message=[%d] [%s]\n",signMessage.length(),signMessage);
			messageBody = signMessage.getBytes();
		}
		byte[] messageHead = NetTool.getMessageHead(nodeid,singType,messageBody.length);

		//调用发送
		byte[] recvByte = httpSendAndRecv(serverIP,serverPort,serverHost,serverUrl,messageHead,messageBody);
		if(recvByte==null){ return false;}

		//重新获取加解密标志
		singType = NetTool.getSingTypeFromHead(messageHead);
		int recvLen = NetTool.getRecvLenFromHead(messageHead);
		System.out.printf("\n接收报文长度[%d]\n", recvLen);

		//解析返回报文
		String messageFile1 = String.format("%s.%s",messageFile,Long.toString(new Date().getTime()));
		if(singType.equalsIgnoreCase("0"))  { //需要解密
			NetTool.printEncMessage("接收到的密文",recvByte,recvByte.length);
			messageBody = secureTool.decrypt(recvByte); //解密

			String recvMessage = new String(messageBody, "UTF-8");
			System.out.printf("已解密报文[%d]=[%s]\n", recvMessage.length(), recvMessage);
//			FileTool.String2File(messageFile1,recvMessage);
//			System.out.printf("已解密报文已写入文件[%s]\n\n",messageFile1);
		} else {
			messageBody = recvByte;
			String recvMessage = new String(messageBody, "UTF-8");
			System.out.printf("未加密报文[%d]=[%s]\n", recvLen, recvMessage);
//			FileTool.String2File(messageFile1,recvMessage);
//			System.out.printf("未加密报文已写入文件[%s]\n\n",messageFile1);

			//如果为明文，但是不是签到报文则直接返回
			if(secureTool.isSignType(messageFile)==false) return true;
			boolean saveFlag = secureTool.saveHandKey(recvMessage);
			if (saveFlag) {
				System.out.printf("会话密钥更新成功\n\n");
			} else {
				System.out.printf("会话密钥更新失败\n\n");
			}
		}
		return true;
	}

	//HTTP方式发送和接收数据
	private static byte[] httpSendAndRecv(String serverIP,String serverPort,String serverHost,String serverUrl,byte[] messageHead,byte[] messageBody) throws Exception
	{
		String httpurl = String.format("http://%s:%s%s",serverIP,serverPort,serverUrl);
		URL url = new URL(httpurl);
		// 建立连接
		System.setProperty("sun.net.http.allowRestrictedHeaders", "true");//取消http头部设置值的限制
		URLConnection conn = url.openConnection();
		// 设置通用的请求头
		conn.setRequestProperty("Accept", "*/*");
		conn.setRequestProperty("User-Agent", "P5HPC");
		conn.setRequestProperty("Content-Type", "text/html");
		conn.setRequestProperty("Content-Length", String.format("%d", messageHead.length+messageBody.length));
		conn.setRequestProperty("Host", serverHost);
		conn.setRequestProperty("Cache-Control", "no-cache");
		conn.setRequestProperty("Connection", "close");
		// 发送POST请求必须设置
		conn.setDoOutput(true);
		conn.setDoInput(true);

		OutputStream out = conn.getOutputStream();
		out.write(messageHead); //发送报文头
		out.write(messageBody); //发送报文体
		out.flush();
		out.close();

		//接收http报文体数据 先接收20位报文头
		InputStream in = conn.getInputStream();
		int totalBytesRcvd = in.read(messageHead, 0, 20);//接收
		if(totalBytesRcvd<20) throw new Exception("接收长度不足20位: " + totalBytesRcvd);

		int onceLen = 0;
		int recvLen = NetTool.getRecvLenFromHead(messageHead);
		byte[] recvByte = new byte[recvLen];//接收数据缓冲

		totalBytesRcvd = 0;
		while(totalBytesRcvd != recvLen) {
			onceLen = in.read(recvByte, totalBytesRcvd, recvLen-totalBytesRcvd);//分段接收
			if(onceLen==-1){ break;}
			totalBytesRcvd += onceLen;
		}
		in.close();

		//报文接收不全
		if ( totalBytesRcvd != recvLen)
		{
			System.out.printf(String.format("报文实际返回长度[%d]与指定长度[%d]不符\n\n", totalBytesRcvd,recvLen));
			return null;
		}
		return recvByte;
	}

	public static void domXmlStr(String xmlStr) {
		// dom解析返回的字符串
//		Document doc = null;
//		try {
//			DocumentHandler.getClassLoader(xmlStr);
//			doc = DocumentHelper.parseText(xmlStr); // 将字符串转为XML
//			Element rootElt = doc.getRootElement(); // 获取根节点
//			System.out.println("根节点：" + rootElt.getName()); // 拿到根节点的名称
//			Iterator iter = rootElt.elementIterator("row"); // 获取根节点下的子节点row
//			Iterator iter1 = rootElt.elementIterator("row1");
//			// 遍历row节点
//			while (iter.hasNext()) {
//				Element recordEle = (Element) iter.next();
//				String users_id = recordEle.elementTextTrim("users_id"); // 拿到row节点下的子节点row值
//				String users_name = recordEle.elementTextTrim("users_name");
//				String users_group = recordEle.elementTextTrim("users_group");
//				String users_address = recordEle.elementTextTrim("users_address");
//				System.out.println("users_id:" + users_id);
//				System.out.println("users_name:" + users_name);
//				System.out.println("users_group:" + users_group);
//				System.out.println("users_address:" + users_address);
//			}
//
//			// 遍历row1节点
//			while (iter1.hasNext()) {
//				Element recordEle = (Element) iter1.next();
//				String users_id = recordEle.elementTextTrim("users_id"); // 拿到row节点下的子节点row值
//				String users_name = recordEle.elementTextTrim("users_name");
//				String users_group = recordEle.elementTextTrim("users_group");
//				String users_address = recordEle.elementTextTrim("users_address");
//				System.out.println("users_id:" + users_id);
//				System.out.println("users_name:" + users_name);
//				System.out.println("users_group:" + users_group);
//				System.out.println("users_address:" + users_address);
//			}
//		} catch (Exception e) {
//			System.out.println("xml解析出错");
//		}
	}


}